/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.statemachine.figure;

import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.FreeformViewport;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.uml2.uml.Element;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.figures.ElementFigure;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;

/**
 * Figure of the StateMachine.
 * 
 * @author David Servat
 * @since 29 jan. 07
 */
public class StateMachineFigure extends NodeFigure{

	/**
	 * Debug channel.
	 */
	private int channel = 501;

	/**
	 * 
	 */
	public static Color classColor = PapyrusPlugin.colorManager.get(new RGB(227,221,239));

	/**
	 * 
	 */
	public static Color classBorderColor= PapyrusPlugin.colorManager.get(new RGB(166,157,183));

	/**
	 * Head of the figure.
	 */
	protected UMLClassHeaderFigure headerFigure;

	/**
	 * Content of the figure.
	 */
	protected UMLClassContentFigure contentFigure = null;

	/**
	 * Old header height.
	 */
	protected int oldHeaderHeight;

	/**
	 * Initial header height.
	 */
	protected int initialHeaderHeight = 20;

	/**
	 * Current header height.
	 */
	protected int currentHeaderHeight = initialHeaderHeight;

	/**
	 * 
	 */
	class UMLClassHeaderFigure extends ElementFigure{

		/**
		 * 
		 */
		public UMLClassHeaderFigure() {
			ToolbarLayout layout = new ToolbarLayout();

			setLayoutManager(layout);
			layout.setSpacing(2);
			this.borderColor = null;
			setOpaque(false);
		}

		/**
		 * setBound is called to resize or move graphical Element by Eclipse
		 * In the case of this package we have to call setDimension Before.
		 * 
		 * @param rect coordinate of the contentPackage.
		 * 
		 * @see setDimension
		 */	
		@Override
		public void setBounds(Rectangle rect){
			super.setBounds(rect);
			nameLabel.setBounds(rect);

			Debug.debug(this,"Bounds are : " +getBounds(), channel);
		}

		/**
		 * Overriden to get rid of the border.
		 * 
		 * @param border 
		 */
		@Override
		protected void paintBorder(Graphics graphics) {};
	}

	/**
	 * Displays the content of the state machine.
	 */
	class UMLClassContentFigure extends ElementFigure{

		/**
		 * 
		 */
		private IFigure pane;

		/**
		 * 
		 */
		protected ScrollPane scrollpane;

		/**
		 * 
		 */
		public UMLClassContentFigure(){
			Debug.debug(this," Call UMLPackageContentFigure", channel);

			//set content layout
			setLayoutManager(new StackLayout());
			//add pane for content
			pane = new FreeformLayer();
			pane.setLayoutManager(new FreeformLayout());

			//add scrollpane
			ScrollPane scrollpane = new ScrollPane();
			FreeformViewport viewport = new FreeformViewport();
			scrollpane.setViewport(viewport);
			scrollpane.setContents(pane);
			this.add(pane);

			//set colors
			setBackgroundColor(headerFigure.getBackgroundColor());
			setBorder(new LineBorder(headerFigure.getBorderColor()));
			setOpaque(false);
		}

		/**
		 * 
		 * 
		 * @return 
		 */
		@Override
		public IFigure getContentPane(){
			return pane;
		}

		/**
		 * setBound is called to resize or move graphical Element by Eclipse
		 * In the case of this package we have to call setDimension Before.
		 * 
		 * @param rect coordinate of the contentPackage.
		 * 
		 * @see setDimension
		 */
		@Override
		public void setBounds(Rectangle rect){
			super.setBounds(rect);
			Debug.debug(this," bounds are : " +getBounds(), channel);
		}

		/**
		 * Overriden to get rid of the border.
		 * 
		 * @param border 
		 */
		@Override
		protected void paintBorder(Graphics graphics) {};
	}

	/**
	 * 
	 */
	public StateMachineFigure(){
		ToolbarLayout layout = new ToolbarLayout();
		setLayoutManager(layout);

		headerFigure = new UMLClassHeaderFigure();
		add(headerFigure);

		contentFigure = new UMLClassContentFigure();
		add(contentFigure);

		setOpaque(false);
	}


	/**
	 * 
	 * 
	 * @param backgroundColor 
	 * 
	 * @see com.cea.papyrus.common.figures.AbstractElementFigure#setBackgroundColor(org.eclipse.swt.graphics.Color)
	 */
	@Override
	public void setBackgroundColor(Color backgroundColor){
		super.setBackgroundColor(backgroundColor);
		headerFigure.setBackgroundColor(backgroundColor);
	}

	/**
	 * 
	 * 
	 * @param color 
	 * 
	 * @see com.cea.papyrus.common.figures.AbstractElementFigure#setFontColor(org.eclipse.swt.graphics.Color)
	 */
	@Override
	public void setFontColor(Color color){
		this.fontColor = color;
		getHeader().setFontColor(color);
	}

	/**
	 * 
	 * 
	 * @param color 
	 * 
	 * @see com.cea.papyrus.common.figures.AbstractElementFigure#setForeGroundColor(org.eclipse.swt.graphics.Color)
	 */
	@Override
	public void setForeGroundColor(Color color){
		super.setForeGroundColor(color);
		contentFigure.setBackgroundColor(color);
	}

	/**
	 * setBound is called to resize or move graphical Element by Eclipse
	 * It call setBound of each subFigure.
	 * In the case of contentPackage we call setDimension
	 * 
	 * @param rect coordinate of the contentPackage.
	 * 
	 * @see setDimension
	 */
	@Override
	public void setBounds(Rectangle rect){
		super.setBounds(new Rectangle(rect));

		//header
		headerFigure.setBounds(new Rectangle(0, 0, rect.width, currentHeaderHeight));
		//compositeContent
		contentFigure.setBounds(new Rectangle(0, currentHeaderHeight, rect.width, rect.height-currentHeaderHeight));

		//specific part of changing the rounded corners
		corner = new Dimension(this.getBounds().getSize());
		corner.height /= 10;
		if(corner.height > getHeadHeight())
			corner.height = getHeadHeight();
		corner.width = corner.height;

		Debug.debug(this," bounds are : " +getBounds(), channel);
	}

	/**
	 * 
	 * 
	 * @param borderColor 
	 */
	@Override
	public void setBorderColor(Color borderColor){
		this.borderColor = borderColor;
	}

	/**
	 * to obtain the header of the package figure.
	 * 
	 * @return IFigure the header
	 */
	public UMLClassHeaderFigure getHeader(){
		return headerFigure;
	}

	/**
	 * Utility methods.
	 */
	public int getCurrentHeaderHeight(){
		return currentHeaderHeight;
	}

	/**
	 * Utility methods.
	 */
	public int getOldHeaderHeight(){
		return oldHeaderHeight;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public IFigure getContentsPane(){
		return contentFigure.getContentPane();
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	protected boolean useLocalCoordinates(){
		return true;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public int getHeadWidth(){
		return headerFigure.getSize().width;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public int getHeadHeight(){ 
		return headerFigure.getSize().height;
	}

	/**
	 * 
	 * 
	 * @return Returns the nameLabel.
	 */
	@Override
	public Label getNameLabel(){
		return headerFigure.getNameLabel();
	}

	/**
	 * 
	 * 
	 * @return Returns the qualifiedNameLabel.
	 */
	@Override
	public Label getQualifiedNameLabel(){
		return headerFigure.getQualifiedNameLabel();
	}

	/**
	 * 
	 * 
	 * @return Returns the nameLabel.
	 */
	@Override
	public Label getStereotypesLabel(){
		return headerFigure.getStereotypesLabel();
	}

	/**
	 * 
	 * 
	 * @param name 
	 */
	@Override
	public void setName(String name){
		headerFigure.setName(name);
	}

	/**
	 * 
	 * 
	 * @param packageName 
	 */
	@Override
	public void setQualifiedName(String packageName){
		headerFigure.setQualifiedName(packageName);
	}

	/**
	 * Set the stereotype value.
	 * If param is null, remove the label.
	 * 
	 * @param stereotypes 
	 */
	@Override
	public void setStereotypes(String stereotypes){
		headerFigure.setStereotypes(stereotypes);
	}

	/**
	 * Refresh presentation of current figure
	 * with presentation specified in a GraphNode.
	 * 
	 * @param presentation 
	 * @param selection 
	 */
	@Override
	public void refreshPresentation(String presentation, Element selection, GraphElement ge){
		headerFigure.refreshPresentation(presentation, selection, ge);
	}

	/**
	 * Refresh list of stereotypes of current EditPart if required
	 * either with or without the first stereotype.
	 * 
	 * @param presentation 
	 * @param hasIcon 
	 * @param hasShape 
	 * @param stereotypes 
	 */
	@Override
	public void refreshStereotypes(String stereotypes, String presentation, boolean hasIcon, boolean hasShape){
		headerFigure.refreshStereotypes(stereotypes, presentation, hasIcon, hasShape);
	}


	/**
	 * Provides specific graphical representation with a line between compartments.
	 * 
	 * @param graphics 
	 */
	@Override
	public void paintFigure(Graphics graphics){
		graphics.setForegroundColor(getBorderColor());
		super.paintFigure(graphics);
		Rectangle rect = getBounds();
		setBounds(rect);
		graphics.setLineStyle(SWT.LINE_SOLID);
		int height = getCurrentHeaderHeight();
		//separator between compartment
		graphics.drawLine(rect.x, rect.y+height, rect.x+rect.width, rect.y+height); 
	}

	/**
	 * Refresh figure.
	 *
	 */
	public void refreshFigure(){
		//header
		oldHeaderHeight = currentHeaderHeight;
		currentHeaderHeight = initialHeaderHeight;
		if(getStereotypesLabel() != null)
			currentHeaderHeight += initialHeaderHeight;
		if(getQualifiedNameLabel() != null)
			currentHeaderHeight += initialHeaderHeight;
	}

}
